#pragma once
#include "Global.h"

#include "List.h"

template <typename I,typename O>
class CombinatorResult;

template <typename I,typename O>
class Combinator;

template <typename I,typename O>
class Combinator_Seq;

template <typename I,typename O>
class Combinator_Alt;

template <typename I,typename O>
class Combinator_Any;

template <typename I,typename O>
class Combinator_List;

template <typename I,typename O>
class Combinator_Opt;

template <typename I,typename O>
class Combinator_And;

template <typename I,typename O>
class Combinator_Not;

template <typename I,typename O>
class Combinator_Node;

template <typename I,typename O>
class Combinator_MemoryManager
{
public:
	~Combinator_MemoryManager()
	{
		Destroy();
	}

	void AddCombinator(Combinator<I,O>* ptr)
	{
		CombinatorList.Add(ptr);
	}

	void AddSeq(Combinator_Seq<I,O>* ptr)
	{
		SeqList.Add(ptr);
	}

	void AddAlt(Combinator_Alt<I,O>* ptr)
	{
		AltList.Add(ptr);
	}

	void AddAny(Combinator_Any<I,O>* ptr)
	{
		AnyList.Add(ptr);
	}

	void AddList(Combinator_List<I,O>* ptr)
	{
		ListList.Add(ptr);
	}

	void AddOpt(Combinator_Opt<I,O>* ptr)
	{
		OptList.Add(ptr);
	}

	void AddAnd(Combinator_And<I,O>* ptr)
	{
		AndList.Add(ptr);
	}

	void AddNot(Combinator_Not<I,O>* ptr)
	{
		NotList.Add(ptr);
	}

	void AddCombinatorNode(Combinator_Node<I,O>* ptr)
	{
		CombinatorNodeList.Add(ptr);
	}

	void AddCombinatorResult(CombinatorResult<I,O>* ptr)
	{
		CombinatorResultList.Add(ptr);
	}

	void Destroy()
	{
		for(int i=0;i<CombinatorList.Size();i++)
		{
			if(CombinatorList[i])
			{
				delete CombinatorList[i];
				CombinatorList[i] = 0;
			}
		}
		CombinatorList.Clear();
		for(int i=0;i<SeqList.Size();i++)
		{
			if(SeqList[i])
			{
				delete SeqList[i];
				SeqList[i] = 0;
			}
		}
		SeqList.Clear();
		for(int i=0;i<AltList.Size();i++)
		{
			if(AltList[i])
			{
				delete AltList[i];
				AltList[i] = 0;
			}
		}
		AltList.Clear();
		for(int i=0;i<AnyList.Size();i++)
		{
			if(AnyList[i])
			{
				delete AnyList[i];
				AnyList[i] = 0;
			}
		}
		AnyList.Clear();
		for(int i=0;i<ListList.Size();i++)
		{
			if(ListList[i])
			{
				delete ListList[i];
				ListList[i] = 0;
			}
		}
		ListList.Clear();
		for(int i=0;i<OptList.Size();i++)
		{
			if(OptList[i])
			{
				delete OptList[i];
				OptList[i] = 0;
			}
		}
		OptList.Clear();
		for(int i=0;i<AndList.Size();i++)
		{
			if(AndList[i])
			{
				delete AndList[i];
				AndList[i] = 0;
			}
		}
		AndList.Clear();
		for(int i=0;i<NotList.Size();i++)
		{
			if(NotList[i])
			{
				delete NotList[i];
				NotList[i] = 0;
			}
		}
		NotList.Clear();
		for(int i=0;i<CombinatorNodeList.Size();i++)
		{
			if(CombinatorNodeList[i])
			{
				delete CombinatorNodeList[i];
				CombinatorNodeList[i] = 0;
			}
		}
		CombinatorNodeList.Clear();
		for(int i=0;i<CombinatorResultList.Size();i++)
		{
			if(CombinatorResultList[i])
			{
				delete CombinatorResultList[i];
				CombinatorResultList[i] = 0;
			}
		}
		CombinatorResultList.Clear();
	}
protected:
	List<Combinator<I,O>*> CombinatorList;
	List<Combinator_Seq<I,O>*> SeqList;
	List<Combinator_Alt<I,O>*> AltList;
	List<Combinator_Any<I,O>*> AnyList;
	List<Combinator_List<I,O>*> ListList;
	List<Combinator_Opt<I,O>*> OptList;
	List<Combinator_And<I,O>*> AndList;
	List<Combinator_Not<I,O>*> NotList;
	List<Combinator_Node<I,O>*> CombinatorNodeList;
	List<CombinatorResult<I,O>*> CombinatorResultList;
};
